package com.baosight.xCyber.service.impl;

import com.baosight.ice.annotation.IceMark;
import com.baosight.xCyber.TagInfo;
import com.baosight.xCyber.TreeManager;
import com.baosight.xCyber.config.EnvConfig;
import com.baosight.xCyber.input.CodeLoad;
import com.baosight.xCyber.input.DataLoad;
import com.baosight.xCyber.dao.IMainNodeMapper;
import com.baosight.xCyber.dao.ITreeNodeMapper;
import com.baosight.xCyber.input.ExcelLoad;
import com.baosight.xCyber.model.TagNode;
import com.baosight.xCyber.model.TreeData;
import com.baosight.xCyber.util.BuildTree;
import com.baosight.xCyber.util.InitTree;
import com.baosight.xCyber.util.SqlSessionFactoryUtil;
import com.zeroc.Ice.Current;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.data.redis.core.RedisTemplate;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.*;


//@IceMark(identity = "${treeIdentity}")
public class TreeManagerI implements TreeManager {

    private ApplicationHome applicationHome = new ApplicationHome(TreeManagerI.class);
    private static Log logger = LogFactory.getLog(TreeManagerI.class);
    public static Map<String, Object> treeDataMap = new HashMap<>();

    @Autowired
    private DataLoad dataLoad;

    @Autowired
    private EnvConfig config;


    @Override
    public String GetTopNodes(Current current) {

        RedisTemplate redisTemplate = config.getRedisTemplate();
        if(redisTemplate!=null){
            return Objects.requireNonNull(redisTemplate.opsForValue().get("tree:root")).toString();
        }
        return treeDataMap.get("tree:root").toString();
    }


    @Override
    public String GetTopNodesByName(String treeName, Current current) {
//        Long startTime = System.currentTimeMillis();
//        System.out.println("方法执行："+new Date(startTime));

        if(treeName == null ||treeName.equals("")){
            treeName = "tree";
        }
        RedisTemplate redisTemplate = config.getRedisTemplate();
        if(redisTemplate!=null) {
            return redisTemplate.opsForValue().get(treeName + ":root").toString();
        }

        String result= treeDataMap.get(treeName + ":root").toString();

//       Long endTime = System.currentTimeMillis();
//        System.out.println("方法执行后:"+new Date(endTime));
//        System.out.println("方法执行耗时:"+(endTime-startTime)+"ms");
        return result;
    }


//    @PostConstruct
    public void initTree() {
        String basePath = applicationHome.getDir() + "/code";
        //String basePath ="src/main/resources/code";
        String[] codeList = new File(basePath).list();
        //code_tree.properties，设置默认读取的code名称（可不存在）
        if(codeList==null||codeList.length==0){
            logger.info("未检测到外部数据源，加载内部默认树tree");
            codeList=new String[1];
            codeList[0]="code_tree.properties";
        }
        for (String codeName : codeList) {
            if (codeName.contains("code")) {
                Map<String, TagNode> returnMap = null;
                //默认树名称
                String treeName = "tree";
                if (codeName.contains("_")) {
                    treeName = codeName.substring(codeName.lastIndexOf("_") + 1, codeName.lastIndexOf("."));
                }
                String fileType = codeName.substring(codeName.lastIndexOf(".") + 1);
                //搜索指定树的树结构
                dataLoad.reloadTreeMap(treeName);
                Map<String, TagNode> mainMap = dataLoad.mainMap;
                Map<String, TagNode> treeMap = dataLoad.treeMap;

                if (mainMap.size() != 0 && treeMap.size() != 0) {
                    //加载数据库中树
                    logger.info(treeName + ":检测到内部数据库相关数据");
                    try {
                        //returnMap = BuildTree.initMap(mainMap, treeMap);
                    } catch (Exception e) {
                        logger.error(treeName+":组装失败，识别外部数据建立树"+e.getMessage());
                        dataLoad.deleteTree(treeName);
                        initTree();
                    }
                } else {
                    //清除数据库中缓存数据信息
                    dataLoad.deleteTree(treeName);
                    //识别外部数据源excel,code文件，生成原始树并储存
                    logger.info(treeName + ":未检测到内部数据，开始识别外部数据源:" + codeName);
                    Map<String, TagNode> mainTemp = null, treeTemp = null;

                    if (fileType.equals("properties")) {
                        //识别外部数据源code文件，收集全部数据：结构（code.properties）+节点（DB2+IHDB）
                        Map<String, TagNode> dataMap = dataLoad.getDataMap(treeName);
                        CodeLoad codeLoad = new CodeLoad();
                        codeLoad.doInit(basePath+"/"+codeName, dataMap);
                        //加载结构点
                        Map<String, TagNode> codeMap = codeLoad.getCodeMap();
                        Map<String, TagNode> titleMap = codeLoad.getTitleMap();
                        if(codeMap.size()!=0){
                            InitTree initTree = new InitTree();
                            //returnMap = initTree.initMap(codeMap, titleMap, dataMap);
                            mainTemp = initTree.mainTemp;
                            treeTemp = initTree.treeTemp;
                        }else{

                            logger.error(treeName+":code规则为空，建立树失败");
                        }

                    } else if (fileType.equalsIgnoreCase("xlsx") || fileType.equalsIgnoreCase("xls")) {

                        ExcelLoad excelLoad = new ExcelLoad();
                        //returnMap = excelLoad.importExcel(basePath+"/"+codeName,config.getExcelProperty());
                        mainTemp = excelLoad.getMainMap();
                        treeTemp = excelLoad.getTreeMap();
                    } else {
                        logger.error(treeName + ":" + codeName + " 未识别成功");
                    }
                    dataLoad.saveData(mainTemp, treeTemp);
                }

                if (returnMap != null) {
                    treeDataMap.put(treeName+ ":root",returnMap.get("root"));
                    treeDataMap.put(treeName, new TreeData(mainMap,treeMap));
                    logger.info(treeName+ ":数据已缓存至内存");
                    RedisTemplate redisTemplate = config.getRedisTemplate();

                    if(redisTemplate!=null) {
                        String str="";
                        for(int i=0;i<1000;i++){
                            str+=returnMap.get("root").toString();
                        }
                        redisTemplate.opsForValue().set(treeName+":root", str);
                        //redisTemplate.opsForHash().putAll(treeName+":leafNode", returnMap);
                        logger.info(treeName + ":数据已缓存至redis");
                    }

//                    if(redisTemplate!=null) {
//                        redisTemplate.opsForValue().set(treeName+":root", returnMap.get("root").toString());
//                        //redisTemplate.opsForHash().putAll(treeName+":leafNode", returnMap);
//                        logger.info(treeName + ":数据已缓存至redis");
//                    }
                }
                System.out.println();
            }
        }
    }


    @Override
    public String GetNodeData(String s, Current current) {
        //redisTemplate.opsForHash().get("leafNode", s).toString();
        return null;
    }

    @Override
    public String updateTree(Current current) {
        //重新生成树
        initTree();
        return "重新生成树成功，请刷新页面";
    }

    @Override
    public String addNode(TagInfo tagInfo, Current current) {
        int result = 0;
        String treeName = tagInfo.treeName;
        TreeData treeData = (TreeData)treeDataMap.get(treeName);
        Map<String, TagNode> main = treeData.getMainNode();
        Map<String, TagNode> tree = treeData.getTreeNode();
        if (tagInfo.tagName == null && tagInfo.parentId == null) {
            return "数据不合法";
        }
        //添加节点时，添加的节点要不在树上，且其父节点要在树上
        if (config.getDB2Server() != null && config.getTreeTable() != null && config.getMainTable() != null) {
            SqlSession session = SqlSessionFactoryUtil.getSqlSession();
            TagNode tagNode = new TagNode(tagInfo);
            //规则=>id<0:表明添加的是结构的点，id>0为数据节点
            if (tagInfo.id == 0) {
                if (main.containsKey(tagInfo.tagName)) {
                    return "添加的节点已存在结构当中，请删除已有的同名节点再重试";
                }
                if (main.containsKey(tagInfo.parentId)) {
                    IMainNodeMapper mainNodeMapper = session.getMapper(IMainNodeMapper.class);
                    result = mainNodeMapper.addNode(tagNode);
                    session.commit();
                    session.close();
                    main.put(tagNode.tagName,tagNode);
                    return result > 0 ? "添加结构成功" : "添加结构失败";
                }
            } else if(tagNode.id>0){
                if (tree.containsKey(tagInfo.tagName)) {
                    return "已存在同名数据节点，请删除已有的同名节点再重试";
                }
                if (main.containsKey(tagInfo.parentId)) {
                    TagNode parentNode = main.get(tagInfo.parentId);
                    if (!parentNode.getItemFlag()) {
                        ITreeNodeMapper treeNodeMapper = session.getMapper(ITreeNodeMapper.class);
                        result = treeNodeMapper.addNode(tagNode);
                        session.commit();
                        session.close();
                        tree.put(tagNode.tagName,tagNode);
                        return result > 0 ? "添加节点失败" : "添加节点成功";
                    } else {
                        return "所添加节点的父节点下存在非数据节点";
                    }
                }
            }
        }
        return "添加失败";
    }

    @Override
    public String modifyNode(TagInfo tagInfo, Current current) {
        int result;
        TagNode tagNode = new TagNode(tagInfo);
        if(tagNode.tagName==null||tagNode.tagName.equals("")||tagNode.parentId==null){
            return "数据不合法！";
        }
        if(config.getDB2Server()!=null){
            SqlSession session = SqlSessionFactoryUtil.getSqlSession();
            String treeName = tagInfo.treeName;
            TreeData treeData = (TreeData)treeDataMap.get(treeName);
            Map<String, TagNode> main = treeData.getMainNode();
            Map<String, TagNode> tree = treeData.getTreeNode();
            if(tagNode.id>0 && config.getTreeTable()!=null){
                String parentName = tagNode.parentId;
                //判断该节点是否存在，其父节点是SqlSession否存在
                if(tree.containsKey(tagNode.tagName) && main.containsKey(parentName)){
                    ITreeNodeMapper treeNodeMapper = session.getMapper(ITreeNodeMapper.class);
                    result = treeNodeMapper.updateNode(tagNode);
                    session.commit();
                    session.close();
                    tree.put(tagNode.tagName,tagNode);
                    return result>0?"数据节点修改成功":"数据节点修改失败";
                }else if(tree.containsKey(tagNode.tagName) && !main.containsKey(parentName)){
                    return "所需更新节点的父节点不在结构中";
                }
            }else if(tagNode.id==0 && config.getMainTable()!=null){
                String parentName = tagNode.parentId;
                if(main.containsKey(tagNode.tagName) && main.containsKey(parentName)){
                    IMainNodeMapper mainNodeMapper = session.getMapper(IMainNodeMapper.class);
                    result = mainNodeMapper.updateNode(tagNode);
                    session.commit();
                    session.close();
                    main.put(tagNode.tagName,tagNode);
                    return result>0?"树结构修改成功":"树结构修改失败";
                }
            }
        }
        return "修改失败";
    }

    @Override
    public String removeTree(String treeName,Current current){
        treeDataMap.remove(treeName);
        return dataLoad.deleteTree(treeName);
    }


    //移除code规则（tagInfo对象至少包含id，tagName，treeName）
    public boolean removeCode(TagInfo tagInfo,Current current){
        if(tagInfo.tagName==null||tagInfo.treeName==null){
            return false;
        }

        int id=tagInfo.id;
        if(config.getIHDBServer()!=null){
            SqlSession session=SqlSessionFactoryUtil.getSqlSession();
            String tagName=tagInfo.tagName;

            TreeData treeData=(TreeData) treeDataMap.get(tagInfo.treeName);
            try {
                if(id==0&&config.getMainTable()!=null){
                    IMainNodeMapper mainNodeMapper=session.getMapper(IMainNodeMapper.class);
                    int i = mainNodeMapper.deleteCode(tagName);
                    treeData.getMainNode().remove(tagName);

                }else if(id>0&&config.getTreeTable()!=null){
                    ITreeNodeMapper treeNodeMapper=session.getMapper(ITreeNodeMapper.class);
                    int i = treeNodeMapper.deleteNode(tagName,tagInfo.treeName);
                    treeData.getTreeNode().remove(tagName);
                }
                return true;
            } catch (Exception e) {
                logger.error("sqlException:"+e.getMessage());
            }
        }
        return false;
    }

}
